#ifndef _GOVT_MODULE_HPP_
#define _GOVT_MODULE_HPP_
/*******************************************************************************
 ** Government Sanctioned Espionage RPG Server                                **
 ** http://www.government-sanctioned.us/                                      **
 **===========================================================================**
 ** Name: module.hpp                                                          **
 ** Description: Code to allow loading and unloading library modules          **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/GOVT/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2011  Barry Gian James <gian@gamingods.net>            **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// $HeadURL: https://govtsanct.svn.codeplex.com/svn/trunk/lib/module.hpp $
// Created on April 4, 2010, 10:03 AM
// Modified $Date: 2012-07-11 23:08:42 -0600 (Wed, 11 Jul 2012) $ by $Author: unknown $
// Portions Copyright 2012 Open Design Strategies, LLC.
// All rights reserved.
#define module_hpp_ID   "$Id: module.hpp 68576 2012-07-12 05:08:42Z unknown $"

#include "common.hpp"
#include "uuid.hpp"
#include <list>

#define DEFAULT_MODULE_DIR	"modules/"

// Use the next two defines if/when you need to create or instantiate data or
// do things before anything else is done/created.  Thing of them as C constructors.
#define EXPORT_INIT_BEGIN 	\
	extern "C" { void _init() {
#define EXPORT_INIT_END		\
	} }

// Use the next two defines if/when you need to do anything after everything
// is torn down but befor exit.
#define EXPORT_FINI_BEGIN	\
	extern "C" { void _fini() {
#define EXPORT_FINI_END		\
	} }

// Every module must have this called one and only one time.
// Taken from KLibLoader, taken from tnmud.  it gives the main program access
// to module's factory class, which is then used to comm w/ the module
#define EXPORT_MODULE( libname, moduleclass ) \
	extern "C" { void * init_ ## libname() { return new moduleclass; } }

enum class ModError { Unknown, NonExist, AlreadyLoaded, NotModule, NoEntry };

class Module
{
public:
	SMART_PTR_DECL(Module)

	Module() { global::UUIDFactory::Create(_uuid); _bInit = _bFini = false; _lib = 0; }
	Module(const std::string & s);

	// Getters
	const std::string & Name() const { return _name; }
	const std::string & Desc() const { return _desc; }
	const std::string & Location() const { return _loc; }
	const std::string & Version() const { return _ver; }
	const std::string & Author() const { return _author; }
	const std::string & Entry() const { return _entry; }
	const bool	InitSupplied() const { return _bInit; }
	const bool	FiniSupplied() const { return _bFini; }
	void *		Library(void * l = 0) { if (l) _lib = l; return _lib; }
	const bool	Loaded() const { return _loaded; }
	const boost::uuids::uuid	UUID() const { return _uuid; }

	// Setters
	void	Name(const std::string & n) { _name = n; }
	void	Desc(const std::string & d) { _desc = d; }
	void	Location(const std::string & l) { _loc = l; }
	void		InitSupplied(const bool b) { _bInit = b; }
	void		FiniSupplied(const bool b) { _bFini = b; }
	void		Version(const std::string & v) { _ver = v; }
	void		Author(const std::string & a) { _author = a; }
	void		Entry(const std::string & e) { _entry = e; }
	void		Loaded(const bool l) { _loaded = l; }



protected:
	boost::uuids::uuid	_uuid;	// generates a new UUID every load
	std::string			_name;
	std::string			_desc;
	std::string			_loc;	// it's file location including file name
	std::string			_ver;
	std::string			_author;
	std::string			_entry;

	bool	_bInit, _bFini;
	bool	_loaded;
	void *	_lib;
};

bool operator == (const Module & m1, const Module & m2);

//! @class ModuleManager
//! @brief Handles loading/unloading/managing runtime modules
class ModuleManager
{
public:
	ModuleManager();
	~ModuleManager();

	int		Init();
	int		LoadModules();
	int		LoadModule(const std::string & m);
	bool	UnloadModule(const std::string & m);
	void	Print() const ;

private:
	std::list<Module::pointer>	modules;
};



#endif /* MODULE_HPP_ */
